home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / CZBindMaker / PrivateSettings / SettingContainer.cs < prev    next >
Text File  |  2003-10-10  |  18KB  |  675 lines

  1. /*****************************************************************************
  2.   Copyright ⌐ 2003 by Martin Cook. All rights are reserved. If you like this 
  3.   code then feel free to go ahead and use it. The only thing I ask is that 
  4.   you don't remove or alter my copyright notice. Your use of this software 
  5.   is entirely at your own risk. I make no claims or warrantees about the 
  6.   reliability or fitness of this code for any particular purpose. If you 
  7.   make changes or additions to this code please mark your code as being 
  8.   yours. If you have questions or comments then please contact me at: 
  9.   martinc@outdrs.net
  10.   
  11.   Have Fun! :o)
  12. *****************************************************************************/
  13.  
  14. using System;
  15. using System.ComponentModel;
  16. using System.Collections;
  17. using System.IO;
  18. using System.IO.IsolatedStorage;
  19. using System.Xml;
  20. using System.Xml.XPath;
  21. using System.Text;
  22. using System.Security;
  23. using System.Security.Cryptography;
  24. using System.Windows.Forms;
  25. using System.Drawing;
  26. using System.Drawing.Design;
  27.  
  28. namespace PrivateSettings
  29. {
  30.  
  31.     /// <summary>
  32.     /// A persistant collection of runtime applications settings.
  33.     /// </summary>
  34.     [ToolboxBitmapAttribute(typeof(SettingContainer), "Images.SettingContainer.bmp")]
  35.     public class SettingContainer : System.ComponentModel.Component
  36.     {
  37.  
  38.         // *******************************************************************
  39.         // Public delegates.
  40.         // *******************************************************************
  41.  
  42.         /// <summary>
  43.         /// Signature for the SettingRead event handler.
  44.         /// </summary>
  45.         public delegate void SettingReadEventHandler(
  46.             object sender, 
  47.             System.EventArgs e
  48.             );
  49.  
  50.         /// <summary>
  51.         /// Signature for the SettingWrite event handler.
  52.         /// </summary>
  53.         public delegate void SettingWriteEventHandler(
  54.             object sender, 
  55.             System.EventArgs e
  56.             );
  57.  
  58.         // *******************************************************************
  59.         // Public events.
  60.         // *******************************************************************
  61.  
  62.         [Description("Fired whenever the settings are read from storage.")]
  63.         public event SettingReadEventHandler SettingRead;
  64.  
  65.         [Description("Fired before the settings are written to storage.")]
  66.         public event SettingWriteEventHandler SettingWrite;
  67.             
  68.         // *******************************************************************
  69.         // Attributes.
  70.         // *******************************************************************
  71.  
  72.         /// <summary>
  73.         /// Required designer variable.
  74.         /// </summary>
  75.         private System.ComponentModel.Container components = null;
  76.  
  77.         /// <summary>
  78.         /// The collection of settings.
  79.         /// </summary>
  80.         private SettingCollection m_coll;
  81.  
  82.         /// <summary>
  83.         /// The file to store settings into.
  84.         /// </summary>
  85.         private string m_fileName;
  86.  
  87.         /// <summary>
  88.         /// Determines whether settings are stored into isolated storage.
  89.         /// </summary>
  90.         private bool m_isolatedStorageFlag;
  91.  
  92.         /// <summary>
  93.         /// Determines whether settings are encrypted before they are stored.
  94.         /// </summary>
  95.         private bool m_encryptedStorageFlag;
  96.  
  97.         /// <summary>
  98.         /// Used to encrypt/decrypt the settings.
  99.         /// </summary>
  100.         private static byte[] c_Key = 
  101.             {
  102.                 0x46, 
  103.                 0x98, 
  104.                 0x13, 
  105.                 0x04, 
  106.                 0x01, 
  107.                 0x99, 
  108.                 0x0A, 
  109.                 0x1D, 
  110.                 0x09, 
  111.                 0x10, 
  112.                 0x3C, 
  113.                 0x46, 
  114.                 0xF8, 
  115.                 0x01, 
  116.                 0x15, 
  117.                 0x12
  118.             };
  119.  
  120.         /// <summary>
  121.         /// Used to encrypt/decrypt the settings.
  122.         /// </summary>
  123.         private static byte[] c_IV = 
  124.             {
  125.                 0x01, 
  126.                 0x42, 
  127.                 0xF3, 
  128.                 0x12, 
  129.                 0x05, 
  130.                 0xA6, 
  131.                 0x01, 
  132.                 0xD8, 
  133.                 0xA9, 
  134.                 0x17, 
  135.                 0x1F, 
  136.                 0x12, 
  137.                 0x1D, 
  138.                 0x14, 
  139.                 0xB5, 
  140.                 0x16
  141.             };
  142.         
  143.         /// <summary>
  144.         /// Used to encrypt/decrypt the settings.
  145.         /// </summary>
  146.         private static RijndaelManaged c_csp = null;
  147.         
  148.         // *******************************************************************
  149.         // Properties.
  150.         // *******************************************************************
  151.  
  152.         /// <summary>
  153.         /// The collection of settings.
  154.         /// </summary>
  155.         [Description("The collection of settings."), 
  156.         DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  157.         [Editor(typeof(PrivateSettings.Design.SettingCollectionEditor),
  158.              typeof(UITypeEditor))]
  159.         public SettingCollection Settings
  160.         {
  161.             get {return m_coll;}        
  162.         } // End Settings
  163.         
  164.         // *******************************************************************
  165.  
  166.         [Description("The file to store settings into.")]
  167.         public string FileName
  168.         {
  169.             get {return m_fileName;}
  170.             set {m_fileName = Path.GetFileName(value);}
  171.         } // End FileName
  172.  
  173.         // *******************************************************************
  174.  
  175.         [Description("Determines whether settings are stored into isolated storage.")]
  176.         public bool IsolatedStorage
  177.         {
  178.             get {return m_isolatedStorageFlag;}
  179.             set {m_isolatedStorageFlag = value;}
  180.         } // End IsolatedStorage
  181.  
  182.         // *******************************************************************
  183.  
  184.         [Description("Determines whether settings are encrypted before they are stored.")]
  185.         public bool EncryptedStorage
  186.         {
  187.             get {return m_encryptedStorageFlag;}
  188.             set {m_encryptedStorageFlag = value;}
  189.         } // End EncryptedStorage
  190.         
  191.         // *******************************************************************
  192.         // Constructors.
  193.         // *******************************************************************
  194.  
  195.         static SettingContainer()
  196.         {
  197.             c_csp = new RijndaelManaged();
  198.             c_csp.Key = c_Key;
  199.             c_csp.IV = c_IV;
  200.         } // End SettingContainer()
  201.  
  202.         // *******************************************************************
  203.  
  204.         public SettingContainer(System.ComponentModel.IContainer container)
  205.         {
  206.  
  207.             container.Add(this);
  208.             InitializeComponent();
  209.  
  210.             // Setup the default values for the attributes.
  211.             m_coll = new SettingCollection();
  212.             m_isolatedStorageFlag = false;
  213.             m_encryptedStorageFlag = true;
  214.  
  215.         } // End SettingContainer()
  216.         
  217.         // *******************************************************************
  218.  
  219.         public SettingContainer()
  220.         {
  221.  
  222.             InitializeComponent();
  223.  
  224.             // Setup the default values for the attributes.
  225.             m_coll = new SettingCollection();
  226.             m_fileName = "settings.xml";
  227.             m_isolatedStorageFlag = false;
  228.             m_encryptedStorageFlag = true;
  229.  
  230.         } // End SettingContainer()
  231.  
  232.         // *******************************************************************
  233.         // Overrides.
  234.         // *******************************************************************
  235.  
  236.         /// <summary>
  237.         /// A sorry excuse for a destructor.
  238.         /// </summary>
  239.         /// <param name="disposing">False if called by the runtime.</param>
  240.         protected override void Dispose(bool disposing) 
  241.         {
  242.             
  243.             // Should we cleanup our list?
  244.             if (disposing)
  245.                 m_coll.Clear();
  246.  
  247.             base.Dispose(disposing);
  248.  
  249.         } // End Dispose()
  250.  
  251.         // *******************************************************************
  252.         // Component Designer generated code.
  253.         // *******************************************************************
  254.  
  255.         #region Component Designer generated code
  256.         /// <summary>
  257.         /// Required method for Designer support - do not modify
  258.         /// the contents of this method with the code editor.
  259.         /// </summary>
  260.         private void InitializeComponent()
  261.         {
  262.             components = new System.ComponentModel.Container();
  263.         }
  264.         #endregion
  265.  
  266.         // *******************************************************************
  267.         // Public methods.
  268.         // *******************************************************************
  269.  
  270.         public void Write()
  271.         {
  272.  
  273.             Stream stream = null;
  274.             XmlTextWriter writer = null;
  275.  
  276.             try
  277.             {
  278.  
  279.                 // Tell the world what is about to happen.
  280.                 _FireSettingWrite();
  281.  
  282.                 // Where should we create the underlying file?
  283.                 if (m_isolatedStorageFlag)
  284.                     stream = new IsolatedStorageFileStream(
  285.                         Path.GetFileName(m_fileName), 
  286.                         FileMode.Create, FileAccess.Write);
  287.                 else
  288.                     stream = File.Create(m_fileName);
  289.                 
  290.                 // Create and configure the writer.
  291.                 writer = new XmlTextWriter(stream, Encoding.UTF8);
  292.                 writer.Formatting = Formatting.Indented;
  293.  
  294.                 // Start the underlying xml document.
  295.                 writer.WriteStartDocument();
  296.  
  297.                 // Create the root element.
  298.                 writer.WriteStartElement("settings");
  299.                 
  300.                 // Loop and save the items.
  301.                 foreach (Setting a in m_coll)
  302.                 {
  303.  
  304.                     // Sanity check the storageKey before attempting to use it.
  305.                     if (a.StorageKey.Length == 0)
  306.                         throw new FormatException("missing storageKey attribute!");
  307.  
  308.                     // Create an element for the setting.
  309.                     writer.WriteStartElement("setting");
  310.                     
  311.                     // Write the storage key attribute for this element.
  312.                     writer.WriteAttributeString("storageKey", 
  313.                         XmlConvert.EncodeName(a.StorageKey));
  314.                     
  315.                     string currentValue;
  316.  
  317.                     // Should we use the current value or the default value?
  318.                     if (a.CurrentValue.Length == 0)
  319.                         currentValue = a.DefaultValue;
  320.                     else
  321.                         currentValue = a.CurrentValue;
  322.                     
  323.                     // Should we encrypt the value?
  324.                     if (m_encryptedStorageFlag == true)
  325.                         currentValue = _Encrypt(currentValue);
  326.                     
  327.                     // Write the value.
  328.                     writer.WriteAttributeString("currentValue", 
  329.                         XmlConvert.EncodeName(currentValue));
  330.  
  331.                     // Finish the setting element.
  332.                     writer.WriteEndElement();
  333.                     
  334.                 } // End foreach item in the collection.
  335.  
  336.                 // Finish the root element.
  337.                 writer.WriteEndElement();
  338.  
  339.                 // Finish the document.
  340.                 writer.WriteEndDocument();
  341.  
  342.             } // End try
  343.  
  344.             finally
  345.             {
  346.  
  347.                 // Should we cleanup the writer?
  348.                 if (writer != null)
  349.                 {
  350.  
  351.                     writer.Flush();
  352.                     writer.Close();
  353.  
  354.                 } // End if we should close the writer.
  355.                 
  356.                 // Should we cleanup the stream?
  357.                 if (stream != null)
  358.                 {
  359.  
  360.                     // NOTE: the stream might have been closed
  361.                     //   when the writer was closed - so we ignore 
  362.                     //   any errors.
  363.  
  364.                     try
  365.                     {
  366.                         stream.Flush();
  367.                         stream.Close();
  368.                     } // End try
  369.  
  370.                     catch (Exception)
  371.                     {
  372.                     } // End catch
  373.  
  374.                 } // End if we should close the stream.
  375.  
  376.             } // End finally
  377.             
  378.         } // End Write()
  379.  
  380.         // *******************************************************************
  381.  
  382.         public void Read()
  383.         {
  384.  
  385.             Stream stream = null;
  386.  
  387.             try
  388.             {
  389.  
  390.                 // Where should we open the underlying file?
  391.                 if (m_isolatedStorageFlag)
  392.                     stream = new IsolatedStorageFileStream(
  393.                         Path.GetFileName(m_fileName), 
  394.                         FileMode.Open, FileAccess.Read);
  395.                 else
  396.                     stream = File.OpenRead(m_fileName);
  397.                                 
  398.                 // Attempt to open the document.
  399.                 XPathDocument doc = new XPathDocument(stream);
  400.  
  401.                 // Create a navigator for the document.
  402.                 XPathNavigator nav = doc.CreateNavigator();
  403.  
  404.                 // Select the list of setting nodes.
  405.                 XPathNodeIterator iter = nav.Select("settings/setting");
  406.  
  407.                 // Loop through the nodes.
  408.                 while (iter.MoveNext())
  409.                 {
  410.                 
  411.                     // Get the value of the attributes. 
  412.                     string storageKey = XmlConvert.DecodeName(
  413.                         iter.Current.GetAttribute("storageKey", ""));
  414.  
  415.                     string currentValue = XmlConvert.DecodeName(
  416.                         iter.Current.GetAttribute("currentValue", ""));
  417.  
  418.                     // Should we decrypt the value?
  419.                     if (m_encryptedStorageFlag == true)
  420.                         currentValue = _Decrypt(currentValue);
  421.                     
  422.                     // Sanity check the storageKey before attempting to use it.
  423.                     if (storageKey.Length == 0)
  424.                         throw new FormatException("missing storageKey attribute!");
  425.  
  426.                     // TODO : look into replacing the ArrayList with a Hashtable...
  427.  
  428.                     // Loop through and find the right setting.
  429.                     foreach (Setting a in m_coll)
  430.                     {
  431.                 
  432.                         // Did we find the right setting?
  433.                         if (a.StorageKey == storageKey)
  434.                         {
  435.                         
  436.                             // Save the new current value.
  437.                             a.CurrentValue = currentValue;
  438.  
  439.                             break;
  440.  
  441.                         } // End if we found the right setting.
  442.  
  443.                     } // End for each setting in the collection.
  444.  
  445.                 } // End while there are more setting nodes.
  446.  
  447.                 // Tell the world what happened.
  448.                 _FireSettingRead();
  449.  
  450.             } // End try
  451.  
  452.             catch (FileNotFoundException)
  453.             {
  454.  
  455.                 // Getting here means that the settings file 
  456.                 //   was not found. Which usually means that it
  457.                 //   hasn't been created yet. So, we iterate 
  458.                 //   through all the settings and set their current
  459.                 //   values to whatever is configured for a default.
  460.  
  461.                 // Loop and configure each Setting
  462.                 foreach (Setting a in m_coll)
  463.                     a.CurrentValue = a.DefaultValue;
  464.                 
  465.                 // Tell the world what happened.
  466.                 _FireSettingRead();
  467.  
  468.             } // End catch
  469.  
  470.             finally
  471.             {
  472.  
  473.                 // Should we cleanup the stream?
  474.                 if (stream != null)
  475.                 {
  476.  
  477.                     // NOTE: the stream might have been closed
  478.                     //   when the document finished reading - so we ignore 
  479.                     //   any errors.
  480.  
  481.                     try
  482.                     {
  483.                         stream.Flush();
  484.                         stream.Close();
  485.                     } // End try
  486.  
  487.                     catch (Exception)
  488.                     {
  489.                     } // End catch
  490.  
  491.                 } // End if we should close the stream.
  492.  
  493.             } // End finally
  494.  
  495.         } // End Read()
  496.         
  497.         // *******************************************************************
  498.         // Private methods.
  499.         // *******************************************************************
  500.  
  501.         /// <summary>
  502.         /// Fires the SettingRead event - checking first to to see if anyone
  503.         /// has subscribed to the event.
  504.         /// </summary>
  505.         private void _FireSettingRead()
  506.         {
  507.  
  508.             // Don't fire events while in the designer.
  509.             if (this.DesignMode)
  510.                 return;
  511.             
  512.             // Fire the event if anyone is listening.
  513.             if (SettingRead != null)
  514.                 SettingRead(this, System.EventArgs.Empty);
  515.  
  516.         } // End _FireSettingRead()
  517.  
  518.         // *******************************************************************
  519.  
  520.         /// <summary>
  521.         /// Fires the SettingWrite event - checking first to to see if anyone
  522.         /// has subscribed to the event.
  523.         /// </summary>
  524.         private void _FireSettingWrite()
  525.         {
  526.  
  527.             // Don't fire events while in the designer.
  528.             if (this.DesignMode)
  529.                 return;
  530.  
  531.             // Fire the event if anyone is listening.
  532.             if (SettingWrite != null)
  533.                 SettingWrite(this, System.EventArgs.Empty);
  534.  
  535.         } // End _FireOnSettingWrite()
  536.  
  537.         // *******************************************************************
  538.  
  539.         private string _Encrypt(string clearValue)
  540.         {
  541.  
  542.             // Sanity check the parameter before attempting to use it.
  543.             if ((clearValue == null) || (clearValue.Length == 0))
  544.                 return "";
  545.  
  546.             ICryptoTransform cryptoTransform = null;
  547.             MemoryStream memoryStream = null;
  548.             CryptoStream cryptoStream = null;
  549.  
  550.             try
  551.             {
  552.  
  553.                 // Convert the string into a byte array.
  554.                 byte[] clearData = Encoding.Default.GetBytes(clearValue);
  555.  
  556.                 // Create the crypto transformer.
  557.                 cryptoTransform = c_csp.CreateEncryptor();
  558.  
  559.                 // Create the crypto stream and the destination stream.
  560.                 memoryStream = new MemoryStream();
  561.                 cryptoStream = new CryptoStream(
  562.                     memoryStream, cryptoTransform, CryptoStreamMode.Write);
  563.                 
  564.                 // Write the data into the crypto (and memory) stream.
  565.                 cryptoStream.Write(clearData, 0, clearData.Length);
  566.                 cryptoStream.FlushFinalBlock();
  567.  
  568.                 // Seek to the beginning.
  569.                 memoryStream.Position = 0;
  570.     
  571.                 // Copy the encrypted data to a buffer.
  572.                 byte[] encryptedData = new byte[memoryStream.Length];
  573.                 memoryStream.Read(encryptedData, 0, (int)memoryStream.Length);
  574.                 
  575.                 // Encode the contents of the buffer.
  576.                 string encryptedValue = Convert.ToBase64String(encryptedData);
  577.  
  578.                 // Return the encrypted value.
  579.                 return encryptedValue;
  580.                 
  581.             } // End try
  582.  
  583.             finally
  584.             {
  585.  
  586.                 // Should we close the crypto stream?
  587.                 if (cryptoStream != null)
  588.                     cryptoStream.Close();
  589.  
  590.                 // Should we close the memory stream?
  591.                 if (memoryStream != null)
  592.                     memoryStream.Close();
  593.  
  594.             } // End finally
  595.             
  596.         } // End _Encrypt()
  597.  
  598.         // *******************************************************************
  599.  
  600.         private string _Decrypt(string encryptedValue)
  601.         {
  602.  
  603.             // Sanity check the parameter before attempting to use it.
  604.             if ((encryptedValue == null) || (encryptedValue.Length == 0))
  605.                 return "";
  606.  
  607.             ICryptoTransform cryptoTransform = null;
  608.             MemoryStream memoryStream = null;
  609.             CryptoStream cryptoStream = null;
  610.  
  611.             try
  612.             {
  613.  
  614.                 // Decode the encrypted data.
  615.                 byte[] encryptedData = Convert.FromBase64String(
  616.                     encryptedValue);
  617.  
  618.                 // Create the crypto transformer.
  619.                 cryptoTransform = c_csp.CreateDecryptor();
  620.                 
  621.                 // Copy the encrypted data into a memory stream.
  622.                 memoryStream = new MemoryStream(encryptedData, 0, 
  623.                     encryptedData.Length);
  624.  
  625.                 // Create the crypto stream.
  626.                 cryptoStream = new CryptoStream(
  627.                     memoryStream, cryptoTransform, CryptoStreamMode.Read);
  628.                 
  629.                 // Copy the decrypted data to a buffer.
  630.                 byte[] clearData = new byte[encryptedData.Length - 1];
  631.                 cryptoStream.Read(clearData, 0, clearData.Length);
  632.         
  633.                 // Convert the data back into a string.
  634.                 string clearValue = Encoding.Default.GetString(clearData);
  635.  
  636.                 // Test for trailing null characters.
  637.                 int index = clearValue.IndexOf((char)0);
  638.  
  639.                 // Should we trim trailing nulls?
  640.                 if (index != -1)
  641.                     clearValue = clearValue.Substring(0, index);
  642.                 
  643.                 // Return the decrypted value.
  644.                 return clearValue;
  645.                 
  646.             } // End try
  647.  
  648.             finally
  649.             {
  650.  
  651.                 // Should we close the crypto stream?
  652.                 if (cryptoStream != null)
  653.                     cryptoStream.Close();
  654.  
  655.                 // Should we close the memory stream?
  656.                 if (memoryStream != null)
  657.                     memoryStream.Close();
  658.  
  659.             } // End finally
  660.  
  661.         } // End _Decrypt()
  662.  
  663.         // *******************************************************************
  664.  
  665.         /// <summary>
  666.         /// If you remove this method, I'll come to your house late at night,
  667.         /// pull up all of your shrubberies, and kick your dog!
  668.         /// </summary>
  669.         private void _DoNothing() { }
  670.  
  671.     } // End class SettingContainer
  672.  
  673. } // End namespace PrivateSettings
  674.  
  675.